package com.ljf.framework.log;

import com.ljf.framework.context.LjfContextManager;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 说明：
 *
 * @Auther: lijinfeng
 * @Date: 2024/5/6
 */
public class LjfLogServiceDefaultImpl extends LjfLogAbstractService {


    @Override
    public Object getSource() {
        return this;
    }

    @Override
    public void error(String log) {
        String dirName = getFolderName("yyyy-MM-dd");
        String fileName = getFileName("yyyy-MM-dd")+"-ERROR.txt";
        String sf = formatLogString(log,LjfLog.ERROR);
        try {
            log(sf,dirName,fileName,LjfLog.ERROR);
        } catch (IOException e) {
            System.err.println("ERROR模式写文件失败."+e.getMessage()+":"+e.getCause());
        }
    }

    @Override
    public void warn(String log) {
        String dirName = getFolderName("yyyy-MM-dd");
        String fileName = getFileName("yyyy-MM-dd")+"-WARN.txt";
        String sf = formatLogString(log,LjfLog.WARN);
        try {
            log(sf,dirName,fileName,LjfLog.WARN);
        } catch (IOException e) {
            System.err.println("WARN模式写文件失败."+e.getMessage()+":"+e.getCause());
        }
    }

    @Override
    public void info(String log) {
        String dirName = getFolderName("yyyy-MM-dd");
        String fileName = getFileName("yyyy-MM-dd")+"-INFO.txt";
        String sf = formatLogString(log,LjfLog.INFO);
        try {
            log(sf,dirName,fileName,LjfLog.INFO);
        } catch (IOException e) {
            System.err.println("INFO模式写文件失败."+e.getMessage()+":"+e.getCause());
        }

    }

    @Override
    public void debug(String log) {
        String dirName = getFolderName("yyyy-MM-dd");
        String fileName = getFileName("yyyy-MM-dd")+"-DEBUG.txt";
        String sf = formatLogString(log,LjfLog.DEBUG);
        try {
            log(sf,dirName,fileName,LjfLog.DEBUG);
        } catch (IOException e) {
            System.err.println("DEBUG模式写文件失败."+e.getMessage()+":"+e.getCause());
        }
    }

    /**
     * 格式化日志格式
     * @param log
     * @param lever
     * @return
     */
    private String formatLogString(String log,String lever){
        String  id;
        try {
            id =  (String) LjfContextManager.getStorage().get("LJF_LOG_ID");
        } catch (Exception e){
            id = "system";
        }

        String sf = String.format("[%tT] %s %s %s %s %s ", new Date(),lever,id , Thread.currentThread().getName(),name,log);
        return sf;
    }

    @Override
    public void error(String log, Throwable e) {
        log += "."+e.getMessage()+":"+e.getCause();
        error(log);
    }

    @Override
    public void warn(String log, Throwable e) {
        log += "."+e.getMessage()+":"+e.getCause();
        warn(log);
    }

    @Override
    public void info(String log, Throwable e) {
        log += "."+e.getMessage()+":"+e.getCause();
        info(log);
    }

    @Override
    public void debug(String log, Throwable e) {
        log += "."+e.getMessage()+":"+e.getCause();
        debug(log);
    }

    @Override
    public void setLogId(String logId) {
        this.id = logId;
    }

    @Override
    public void setLogName(String name) {
        this.name = name;
    }


    /**
     * 记录日志
     * @param log 日志信息
     * @param FolderName 文件夹名称
     * @param fileName 文件名
     * @param level 日志级别
     * @throws IOException 可能产生IO异常，如读写错误
     */
    public synchronized void log(String log,String FolderName,String fileName,String level) throws IOException{
        if(!checkFile(FolderName,fileName)){//如果文件夹和文件都存在
            makeFile(FolderName,fileName);
        }

        //记录日志文件
        FileOutputStream fo = null;
        try{
            fo = new FileOutputStream(LjfLog.LOG_FOLDER+"/"+FolderName+"/"+fileName,true);
            fo.write((log+"\n").getBytes());
            fo.flush();
            if(LjfLog.ERROR.equals(level)){
                System.err.println(log);
            }else{
                System.out.println(log);
            }
        } catch (FileNotFoundException e) {
            throw e;
        } catch (IOException e) {
            throw e;
        }finally{
            if(null != fo){
                try {
                    fo.flush();
                    fo.close();
                } catch (IOException e) {
                    System.out.println("关闭文件:"+LjfLog.LOG_FOLDER+"/"+FolderName+"/"+fileName+" 失败！");
                }
            }
        }
    }


    /**
     * 按照指定的文件夹名和文件名创建文件
     * @param floaderName 文件夹名
     * @param fileName 文件名
     */
    private void makeFile(String floaderName, String fileName) {
        if(null == floaderName || null == fileName){
            System.err.println("文件夹或文件名为空！");
            return;
        }
        File root = new File(LjfLog.LOG_FOLDER);
        try{
            if(!root.isDirectory()){
                if(!root.mkdir()){
                    if(!root.mkdir()){//多次创建失败，返回系统退出
                        System.err.println("无法创建日志文件的根目录："+LjfLog.LOG_FOLDER+"/。程序退出！");
                        System.exit(0);
                    }
                }
            }
        }catch(SecurityException  e){
            System.err.println("创建日志文件出错(权限不足)."+e.getMessage());
            System.err.println("程序退出！");
            System.exit(0);
        }
        File floader = new File(LjfLog.LOG_FOLDER+"/"+floaderName);
        if(root.isDirectory()){//root目录创建成功，创建yyyy-MM-dd文件夹
            if(!floader.isDirectory()){
                try{
                    if(!floader.mkdir()){
                        if(!floader.mkdir()){
                            System.err.println("无法创建日志文件夹："+LjfLog.LOG_FOLDER+"/"+floaderName+"/。程序退出！");
                            System.exit(0);
                        }
                    }
                }catch(SecurityException  e){
                    System.err.println("创建日志文件夹出错(权限不足)."+e.getMessage());
                    System.err.println("程序退出！");
                    System.exit(0);
                }
            }
        }
        //文件夹创建成功则创建文件
        File file = new File(LjfLog.LOG_FOLDER+"/"+floaderName+"/"+fileName);
        if(floader.isDirectory()){
            if(!file.isFile()){//文件不存在
                try{
                    if(!file.createNewFile()){
                        if(!file.createNewFile()){
                            System.err.println("无法创建日志文件："+LjfLog.LOG_FOLDER+"/"+floaderName+"/。程序退出！");
                            System.exit(0);
                        }
                    }
                }catch(SecurityException  e){
                    System.err.println("创建日志文件出错(权限不足)."+e.getMessage());
                    System.err.println("程序退出！");
                    System.exit(0);
                } catch (IOException e) {
                    System.err.println("创建日志文件出错."+e.getMessage());
                    System.err.println("程序退出！");
                    System.exit(0);
                }

            }
        }
        if(file.exists()){
            return ;
        }
    }

    /**
     * 判断文件是否存在
     * @param dirName 文件夹名
     * @param fileName 文件名
     * @return 都存在则返回true，否则返回false
     */
    private boolean checkFile(String dirName, String fileName) {
        File directory = new File(LjfLog.LOG_FOLDER+"/"+dirName);
        if(directory.isDirectory()){//文件加存在
            //判断文件是否存在
            File file = new File(LjfLog.LOG_FOLDER+"/"+dirName+"/"+fileName);
            if(file.isFile()){
                return true;
            }
        }
        return false;
    }



    /**
     * 获取制定格式的文件夹名字
     * @param string 日期格式，必须符合JAVA规范
     * @return
     */
    public synchronized String getFolderName(String string) {
        try{
            SimpleDateFormat sf = new SimpleDateFormat(string);
            Date date = new Date();
            return sf.format(date);
        }catch(IllegalArgumentException e){
            System.err.println("不符合JAVA规范的参数！采取默认参数格式：yyyy-MM-dd");
            getFolderName("yyyy-MM-dd");
        }
        return null;
    }
    /**
     * 获取文件名字
     * @param string 日期格式，必须符合JAVA规范
     * @return
     */
    public  synchronized String getFileName(String string) {
        try{
            SimpleDateFormat sf = new SimpleDateFormat(string);
            Date date = new Date();
            return sf.format(date);
        }catch(IllegalArgumentException e){
            System.err.println("不符合JAVA规范的参数！采取默认参数格式：yyyy-MM-dd");
            getFolderName("yyyy-MM-dd");
        }
        return null;
    }


}
